home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 05 / 6 / DISK0564.ZIP / SOURCE.ARC / MV.ASM < prev    next >
Assembly Source File  |  1989-04-02  |  42KB  |  1,028 lines

  1.         TITLE MV - MSDOS FILE MOVE UTILITY
  2.         PAGE 55,132
  3. ;***************************************************************************
  4. ;       THIS PROGRAM RENAMES A FILE OR DIRECTORY, OR MOVES ONE OR MORE FILES
  5. ;       OR DIRECTORIES BETWEEN DISKS OR DIRECTORIES.
  6. ;
  7. ;       USAGE (afn = ambiguous file name, ufn = unambiguous file name,
  8. ;              dir = directory):
  9. ;
  10. ;               MV ufn1 ufn2    - renames or moves ufn1 to ufn2.
  11. ;
  12. ;               MV afn1 afn2 ... dir  - moves one or more files into dir.
  13. ;
  14. ;               MV -R dir1 dir2  if dir2 doesn't exist, renames or moves
  15. ;                                 dir1 to dir2.
  16. ;                                 (note: DOS 2 requires that renaming a direc-
  17. ;                                 tory be done by creating dir2, moving all
  18. ;                                 files from dir1 into it, then deleting dir1).
  19. ;
  20. ;                               - if dir2 exists, makes dir1 a subdirectory
  21. ;                                 of it.
  22. ;
  23. ;       SWITCHES (OPTIONAL):
  24. ;
  25. ;        I  prompts before overwriting files
  26. ;
  27. ;        R  allows recursively moving directories.
  28. ;
  29. ;               V  turns on "verbose" mode (shows name of each file as it
  30. ;                      is moved).
  31. ;***************************************************************************
  32. ;       BY: JON DART
  33. ;           3012 HAWTHORN ST.,
  34. ;           SAN DIEGO, CA 92104
  35. ;***************************************************************************
  36. ;   TO BUILD MV.EXE:
  37. ;    MASM MV,MV,NUL,NUL
  38. ;    LINK MV,MV,NUL,ASM
  39. ;    EXEPACK MV.EXE MV.NEW
  40. ;    DEL MV.EXE
  41. ;    REN MV.NEW=MV.EXE
  42. ;***************************************************************************
  43. ;    Version 3.3, 30-Mar-89 moves with root directory as destination
  44. ;                now handled correctly.  Also a bug fix in
  45. ;                procedure SETUP_SRC_DIR.
  46. ;    Version 3.2, 19-Jan-89 fix to FIXPATH; relinked
  47. ;    Version 3.1, 03-Nov-88 disallows MV afn foo if foo doesn't exist.
  48. ;    Version 3.0, 24-Sep-88 bug fix in FIXPATH; relinked
  49. ;    Version 2.5, 09-Feb-88 assembles under MASM 5.0
  50. ;       Version 2.4, 30-May-87 fixes a bug causing file deletion when source
  51. ;                              is in current directory and dest is omitted.
  52. ;    Version 2.3, 28-Nov-86 fixes bug involving relative directory moves
  53. ;                   (e.g. mv -r ..\foo .)
  54. ;    Version 2.2, 24-Oct-86 switch parser allows -rvi as well as -r -v -i
  55. ;    Version 2.1, 06-Jul-86 changes to memory alloc, allows hyphen for
  56. ;                switches, now assembles under masm 4.0
  57. ;    Version 2.0, 30-Jun-86 minor cleaning up, r and i switches added, c
  58. ;                switch removed
  59. ;       Version 1.9, 26-Apr-86 doesn't exit after user responds n to 
  60. ;                    overwrite msg.
  61. ;       Version 1.8, 31-Mar-86 more bug fixes (*sigh*)
  62. ;       Version 1.7, 29-Mar-86 bug fixes
  63. ;       Version 1.6, 24-Mar-86 allows multiple source files
  64. ;       Version 1.5, 25-Jan-86 adds check for identical source & dest
  65. ;       Version 1.4, 14-Jan-86 adds switches
  66. ;       Version 1.3, 12-Jan-86 adds recursion
  67. ;       Version 1.2, 01-Jan-86
  68. ;       Version 1.1, 01-Nov-85
  69. ;       Version 1.0, 29-Sep-85
  70. ;***************************************************************************
  71.  
  72.     DOSSEG
  73.     .MODEL    SMALL
  74.  
  75. PATHSIZE EQU    65                      ;MAX. SIZE OF DOS PATHNAME, +1
  76. BUFSIZE EQU     32*1024                 ;SIZE OF COPY BUFFER
  77. MAXLEVEL EQU    12                      ;MAX NESTING LEVEL FOR DIRECTORIES
  78. MAXARGS EQU     40                      ;MAXIMUM # OF COMMAND LINE ARGUMENTS
  79. TRUE    EQU     0FFH
  80. FALSE   EQU     0
  81. CONFIRM EQU     FALSE                   ;"CONFIRM BEFORE OVERWRITE" OPTION (DEFAULT VALUE)
  82. RECURSE EQU    FALSE            ;"RECURSE" OPTION (DEFAULT VALUE)
  83. VERBOSE EQU     FALSE                   ;"VERBOSE" OPTION (DEFAULT VALUE)
  84. M       EQU     BYTE PTR 0[BX]
  85. BIT$DIR EQU     00010000B               ;BIT IN ATTRIBUTE FOR DIRECTORY
  86. BIT$RO  EQU     00000001B               ;BIT IN ATTRIBUTE FOR WRITE-PROTECT
  87.  
  88.         .XLIST
  89.         INCLUDE ASCII.DEF
  90.         INCLUDE MSDOS2.DEF
  91.     INCLUDE MACROS.DEF
  92.         .LIST
  93.  
  94. MVINFO  STRUC
  95. NEWDIR  DW      1 DUP (?)               ;FLAG, =1 IF NEW DIRECTORY CREATED
  96. SRCTYPE DB     2 DUP (?)                ;TYPE OF SOURCE (0 IF UFN)
  97. DESTTYPE DB     2 DUP (?)        ;TYPE OF DEST (0 IF UFN)
  98. ARG1    DB      PATHSIZE DUP (?)        ;FIRST ARGUMENT (SOURCE)
  99. ARG2    DB      PATHSIZE DUP (?)        ;SECOND ARGUMENT (DEST)
  100. ARG2A   DB      PATHSIZE DUP (?)        ;SOURCE PREFIX + DEST
  101. SSPATH  DB      PATHSIZE DUP (?)        ;SOURCE SEARCH PATH
  102. SPREFIX DB      PATHSIZE DUP (?)        ;SOURCE LEAD-IN PATH
  103. DSPATH  DB      PATHSIZE DUP (?)        ;DEST SEARCH PATH
  104.                                         ;(USED ONLY AS SCRATCH AREA)
  105. DPREFIX DB      PATHSIZE DUP (?)        ;DEST LEAD-IN PATH
  106. SRCNAME DB      PATHSIZE DUP (?)        ;UNAMBIGUOUS SOURCE NAME
  107. DESTNAME DB     PATHSIZE DUP (?)        ;UNAMBIG. DEST NAME
  108. DTA     DB      128 DUP (?)             ;DTA FOR SEARCH FN.
  109. MVINFO  ENDS
  110. MVSTRUCSIZE EQU 9*PATHSIZE+135          ;SIZE OF STRUCTURE
  111.  
  112.     .DATA
  113. ;       INITIALIZED DATA STORAGE:
  114. ;
  115. MSG1    DB 'MV Version 3.3 by Jon Dart (30-Mar-89)',CR,LF,CR,LF
  116.         DB 'USAGE (afn = ambiguous file name, ufn = unambiguous file name,'
  117.         DB CR,LF
  118.         DB '       dir = directory):',CR,LF,CR,LF
  119.         DB 'MV ufn1 ufn2          move or rename ufn1 to ufn2.',CR,LF,CR,LF
  120.         DB 'MV afn1 afn2 ... dir  move one or more files into dir.',CR,LF,CR,LF
  121.         DB "MV -R dir1 dir2       if dir2 doesn't exist, move or rename"
  122.         DB CR,LF
  123.         DB '                      dir1 to dir2.',CR,LF,CR,LF
  124.         DB '                      if dir2 exists, make dir1 a subdirectory'
  125.         DB CR,LF
  126.         DB '                      of it.',CR,LF,CR,LF
  127.         DB 'SWITCHES (OPTIONAL):',CR,LF,CR,LF
  128.         DB '-I   prompt before overwriting files.',CR,LF,CR,LF
  129.     DB '-R   allow recursive moving of directories.',CR,LF,CR,LF
  130.         DB '-V   echo file names as they are moved.',CR,LF
  131.         DB 0
  132. MSG2    DB      ': file not found.',CR,LF,0
  133. MSG3    DB      'Source and dest are incompatible.',CR,LF,0
  134. MSG4    DB      ' exists. Overwrite [Y or N]? ',0
  135. MSG5    DB      ': open failed.',CR,LF,0
  136. MSG6    DB      ': file is R/O. Are you SURE [Y or N]? ',0
  137. MSG7    DB    ': directory.',CR,LF,0
  138. MSG8    DB      ': write error.',CR,LF,0
  139. MSG9    DB      '; read error.',CR,LF,0
  140. MSG10   DB      ': write error (probably disk full).',CR,LF,0
  141. MSG11   DB      ': rename failed.',CR,LF,0
  142. MSG12   DB      ": can't create.",CR,LF,0
  143. MSG13   DB      ": can't remove.",CR,LF,0
  144. MSG14   DB      "Directories nested too deep.",CR,LF,0
  145. ; MSG15   DB      "Insufficient memory for buffers.",CR,LF,0
  146. MSG16   DB      ": Illegal switch.",CR,LF,0
  147. MSG17   DB      "Error: source and dest are identical.",CR,LF,0
  148. MSG18   DB      "Too many arguments.",CR,LF,0
  149. SWLIST  DB    'IRV',0        ;LIST OF LEGAL SWITCHES
  150.  
  151.     .STACK
  152.         DB      512 DUP (?)
  153.  
  154.     .DATA?
  155. ;    UNINITIALIZED DATA AND BUFFER AREAS       
  156.  
  157. RBASE   DW     1 DUP (?)               ;POINTER TO MVSTRUC IN RSTACK
  158. LEVEL   DW      1 DUP (?)               ;RECURSION LEVEL
  159. SRCDRIVE  DW    1 DUP (?)               ;SOURCE DRIVE (0 = DEFAULT)
  160. DESTDRIVE  DW   1 DUP (?)               ;DEST DRIVE (0 = DEFAULT)
  161. INHANDLE DW    1 DUP (?)               ;INPUT FILE HANDLE
  162. OUTHANDLE DW    1 DUP (?)               ;OUTPUT FILE HANDLE
  163. IFLAG   DW    1 DUP (?)               ;CONFIRM FLAG
  164. RFLAG    DW    1 DUP (?)        ;RECURSIVE FLAG
  165. VFLAG   DW    1 DUP (?)               ;VERBOSE FLAG
  166. CMDTAIL DB    128 DUP (?)             ;STORAGE FOR COMMAND TAIL
  167. DEST_DTA DB     128 DUP (?)             ;HOLDS INFO ON DEST, RETURNED FROM DOS
  168.                                         ;FN 4E.
  169. NUMARGS DW      1 DUP (?)               ;NUMBER OF ARGUMENTS ON COMMAND LINE
  170. ARGPTRS DW      MAXARGS DUP (?)         ;POINTERS TO START OF ARGUMENTS
  171. BUFFER  DB      BUFSIZE DUP (?)         ;FILE XFER BUFFER
  172. RSTACK  MVINFO  MAXLEVEL DUP (<>)    ;RECURSION STACK
  173.  
  174.         PAGE +
  175.     .CODE
  176.  
  177. EXTRN   CPYCNT:NEAR,UC:NEAR,UCSTR:NEAR,CRLF:NEAR,ERRORMSG:NEAR,COUT:NEAR
  178. EXTRN   CIN:NEAR,CLRCO:NEAR,SKIPSP:NEAR,TYPTX:NEAR,ERRORMSG:NEAR,CLRCO:NEAR
  179. EXTRN   CMDSRC:NEAR,FIXPATH:NEAR,GETYORN:NEAR,UNLINK2:NEAR
  180. EXTRN   TYPE_DIR:ABS,TYPE_AFN:ABS,TYPE_UFN:ABS,TYPE_DSP:ABS,TYPE_DRV:ABS
  181. EXTRN   TYPE_UNK:ABS
  182.  
  183. ;*********************
  184. ;* MACRO DEFINITIONS *
  185. ;*********************
  186.  
  187. ADDR    MACRO   REG,OFFST               ;COMPUTE ADDRESS OFFSET FROM BASE REGISTER (BX)
  188.         MOV     REG,BX
  189.         ADD     REG,OFFST
  190.         ENDM
  191.  
  192. ERROR   MACRO   ERRNUM                  ;SHOW ERROR MESSAGE
  193.         MOV     DX,OFFSET DGROUP:MSG&ERRNUM
  194.     CALL    PRTERR
  195.         ENDM
  196.  
  197. COPYPATH MACRO  SOURCE,DEST             ;COPY PATHNAME FROM SOURCE TO DEST
  198.         ADDR    SI,SOURCE
  199.         ADDR    DI,DEST
  200.         MOV     CX,PATHSIZE
  201.         CALL    CPYCNT
  202.         ENDM
  203.  
  204. ;**********************
  205. ; PROGRAM ENTRY POINT *
  206. ;**********************
  207. ENTRY:
  208.         TEST_DOS2                       ;TEST FOR DOS 2.0, EXIT IF DOS 1
  209.     MOV    AX,DGROUP
  210.     MOV    ES,AX
  211. MEMOK:
  212.         MOV     BX,80H                  ;POINT TO BYTE COUNT FOR COMMAND LINE
  213.         CMP     [BX],BYTE PTR 0
  214.         JE      USEMSG                  ;IF NO COMMAND TAIL
  215.         PUSH    BX
  216.         MOV     DL,[BX]
  217.         MOV     DH,0
  218.         ADD     BX,DX
  219.         INC     BX
  220.         MOV     [BX],BYTE PTR 0         ;PUT 0 BYTE AT END OF COMMAND LINE
  221.         POP     BX
  222.         INC     BX
  223.         CALL    UCSTR                   ;CONVERT COMMAND LINE TO UPPER CASE
  224.         CALL    SKIPSP                  ;SKIP LEADING SPACES
  225.         JNC     L_2                     ;IF SOMETHING ON LINE
  226. USEMSG: ERROR   1
  227.     MOV    AL,1            ;SET ERROR CODE
  228.         JMP     EXIT2
  229. L_2:
  230.         MOV     SI,BX
  231.         MOV     DI,OFFSET ES:CMDTAIL
  232.         MOV     CX,128
  233.         CALL    CPYCNT                  ;SAVE COMMAND TAIL
  234.         MOV     AX,ES
  235.         MOV     DS,AX                   ;SET DATA SEG TO VARIABLE AREA
  236.         MOV     BYTE PTR DS:IFLAG,CONFIRM  ;SET CONFIRM FLAG DEFAULT
  237.         MOV     BYTE PTR DS:VFLAG,VERBOSE  ;SET VERBOSE FLAG DEFAULT
  238.     MOV    BYTE PTR DS:RFLAG,FALSE    ;SET RECURSIVE FLAG DEFAULT
  239.     MOV    WORD PTR DS:LEVEL,0    ;SET RECURSION LEVEL = 0
  240.         MOV     BYTE PTR DS:SRCDRIVE,0  ;SET SOURCE DRIVE DEFAULT
  241.         MOV     BYTE PTR DS:DESTDRIVE,0 ;SET DEST DRIVE DEFAULT
  242. ;***************************
  243. ; COLLECT SWITCHES, IF ANY *
  244. ;***************************
  245.         MOV     BX,OFFSET CMDTAIL       ;POINT TO COMMAND TAIL
  246. NEXTSW:
  247.         CALL    SKIPSP
  248.         JB      USEMSG                  ;IF NOTHING ON LINE BESIDES SWITCHES
  249.         CMP     BYTE PTR [BX],'/'       ;SWITCH SPECIFIED?
  250.         JE    GOTSW            ;YES
  251.     CMP    BYTE PTR [BX],'-'    ;CHECK FOR HYPHEN, TOO
  252.     JNE    NOSWITCH
  253. GOTSW:
  254.         INC     BX                      ;SKIP OVER SWITCH CHARACTER
  255.         CALL    SKIPSP                  ;SKIP LEADING BLANKS
  256.         JB      USEMSG                  ;IF NOTHING
  257. SWLOOP:
  258.         CALL    UC                      ;MAKE SWITCH UPPER CASE
  259.     PUSH    DS
  260.     PUSH    BX
  261.     PUSH    AX
  262.     MOV    AX,DGROUP
  263.     MOV    DS,AX
  264.     POP    AX
  265.     MOV    BX,OFFSET SWLIST
  266.     CALL    CMDSRC            ;SEARCH LIST OF VALID SWITCHES
  267.     POP    BX
  268.     POP    DS
  269.     MOV    AH,0
  270.     ADD    AX,AX            ;NOT FOUND IN LIST?
  271.     JZ    BADSWITCH        ;NO.
  272.     MOV    SI,OFFSET IFLAG - 2
  273.     ADD    SI,AX            ;POINT TO FLAG
  274.     NOT    WORD PTR [SI]        ;1'S COMPLEMENT
  275.     INC    BX
  276.     MOV    AL,BYTE PTR [BX]    ;GET NEXT CHAR. FROM LINE
  277.     CMP    AL,SPACE
  278.     JE    NEXTSW            ;IF SPACE, LOOK FOR - OR FILENAME
  279.     CMP    AL,TAB
  280.     JE    NEXTSW            ;IF TAB, LOOK FOR - OR FILENAME
  281.     JMP    SWLOOP            ;ELSE ASSUME THIS IS A SWITCH CHAR.
  282. BADSWITCH:
  283.     MOV    AL,BYTE PTR [BX]
  284.         CALL    COUT                    ;DISPLAY BAD CHAR.
  285.         ERROR   16                      ;ILLEGAL SWITCH
  286.     MOV    AL,16            ;SET ERROR CODE
  287.         JMP     EXIT2
  288. ;************************************************************
  289. ; SCAN THE COMMAND LINE AND STORE POINTERS TO ALL ARGUMENTS *
  290. ;************************************************************
  291. NOSWITCH:
  292.         MOV     CX,0                    ;CX COUNTS # OF ARGUMENTS
  293.         MOV     SI,OFFSET DS:ARGPTRS    ;POINT TO ARG POINTER TABLE
  294. SAVEARG:
  295.         INC     CX                      ;BUMP ARGUMENT COUNT
  296.         CMP     CX,MAXARGS
  297.         JG      TOOMANY                 ;IF TOO MANY
  298.         MOV     DS:[SI],BX              ;SAVE POINTER TO ARG
  299.         ADD     SI,2                    ;ADVANCE TO NEXT TABLE ENTRY
  300. CNTARGS:
  301.         MOV     AL,DS:[BX]              ;GET CHAR. FROM COMMAND LINE
  302.         CMP     AL,0
  303.         JE      ENDLINE                 ;IF END OF LINE
  304.         COMPLIST <SPACE,TAB>,NEXTARG    ;SEE IF SPACE OR TAB
  305.         INC     BX
  306.         JMP     CNTARGS                 ;LOOP TILL DELIMITER FOUND
  307. NEXTARG:
  308.         CALL    SKIPSP                  ;SKIP SPACES AND TABS
  309.         JNB     SAVEARG                 ;IF NOT EOL, BACK TO TOP OF LOOP
  310. ENDLINE:
  311.         CMP     CX,0                    ;CHECK ARGUMENT COUNT
  312.         JE      NOARGS                  ;IF NO ARGS
  313.         CMP     CX,1
  314.         JG      ARGSOK                  ;IF >=2 ARGS
  315.         MOV     DS:[SI],BX              ;EXACTLY ONE ARGUMENT, SO
  316.         INC     CX                      ;MAKE A DUMMY (NULL) 2ND ARGUMENT
  317.         JMP     SHORT ARGSOK
  318. NOARGS:
  319.         JMP     USEMSG                  ;ELSE USE MESSAGE
  320. TOOMANY:
  321.         ERROR   18                      ;TOO MANY ARGUMENTS (PRETTY UNLIKELY)
  322.     MOV    AL,18            ;SET ERROR CODE
  323.         JMP     EXIT2
  324. ;************************************
  325. ;* COLLECT THE DESTINATION PATHNAME *
  326. ;************************************
  327. ARGSOK: MOV     WORD PTR DS:NUMARGS,CX  ;SAVE NUMBER OF ARGUMENTS
  328.         DEC     CX                      ;NUMBER OF ARGS - 1
  329.         ADD     CX,CX                   ;TIMES TWO
  330.         MOV     SI,OFFSET DS:ARGPTRS
  331.         ADD     SI,CX                   ;POINT TO ADDR. OF LAST ARGUMENT (DEST)
  332.         MOV     BX,DS:[SI]              ;PUT ADDR. INTO BX
  333.         MOV     DI,OFFSET RSTACK.ARG2   ;POINT TO STORAGE FOR DEST
  334.         MOV     AL,[BX+1]
  335.         CMP     AL,':'                  ;CHECK FOR DEST DRIVE SPEC
  336.         JNE     GETLAST                 ;IF NONE
  337.         MOV     AL,[BX]                 ;DRIVE SPECIFIED, GET DRIVE LETTER
  338.         SUB     AL,'A'-1                ;MAKE BINARY
  339.         MOV     BYTE PTR DS:DESTDRIVE,AL   ;SAVE DRIVE
  340. GETLAST: MOV    AL,[BX]                 ;GET A CHAR. FROM CMD LINE
  341.         COMPLIST <0,SPACE,TAB>,ENDARG2  ;IF DELIMITER
  342.         STOSB                           ;NOT DELIMITER, STORE IT
  343.         INC     BX                      ;BUMP POINTER
  344.         JMP     GETLAST                 ;LOOP
  345. ENDARG2:
  346.         MOV     AL,0
  347.         STOSB                           ;END DEST W. 0
  348. ;***********************************************************
  349. ;* LOOP, TAKING ONE SOURCE AT A TIME AND MOVING IT TO DEST *
  350. ;***********************************************************
  351.         MOV     CX,WORD PTR DS:NUMARGS  ;GET NUMBER OF ARGS AGAIN
  352.         DEC     CX                      ;-1
  353.         MOV     SI,OFFSET DS:ARGPTRS    ;POINT TO POINTER TABLE
  354. MOVE1ARG:
  355.         MOV     BX,DS:[SI]              ;GET POINTER TO ARG
  356.         PUSH    SI
  357.         PUSH    CX
  358.         CALL    MOVEARG                 ;MOVE IT
  359.         POP     CX
  360.         POP     SI
  361.         ADD     SI,2                    ;ADVANCE TO NEXT ARG POINTER
  362.         LOOP    MOVE1ARG                ;LOOP TILL NO MORE ARGS TO MOVE
  363.     MOV    AL,0            ;ERROR CODE 0 MEANS OK
  364.         JMP     EXIT2
  365.  
  366. ;**********************************
  367. ;* MOVE 1 SOURCE ARGUMENT TO DEST *
  368. ;**********************************
  369. MOVEARG PROC   NEAR
  370.         MOV     BYTE PTR DS:SRCDRIVE,0  ;SET SOURCE DRIVE DEFAULT
  371.         MOV     DI,OFFSET RSTACK.ARG1   ;COLLECT SOURCE
  372.         MOV     AL,[BX+1]
  373.         CMP     AL,':'                  ;CHECK FOR SOURCE DRIVE SPEC
  374.         JNE     GETARG
  375.         MOV     AL,[BX]                 ;GET DRIVE LETTER
  376.         SUB     AL,'A'-1                ;MAKE BINARY
  377.         MOV     BYTE PTR DS:SRCDRIVE,AL ;SAVE SOURCE DRIVE
  378. GETARG: MOV     AL,[BX]                 ;COPY FROM [BX] TO [DI] UNTIL DELIMITER
  379.         COMPLIST <0,SPACE,TAB>,ENDARG
  380.         STOSB
  381.         INC     BX
  382.         JMP     GETARG
  383. ENDARG: MOV     AL,0
  384.         STOSB                           ;END ARG1 W. ZERO
  385.         MOV     WORD PTR DS:RBASE,OFFSET RSTACK   ;SAVE OFFSET TO RSTACK
  386.         CALL    MOVEIT                  ;DO THE STUFF
  387.         RET
  388. MOVEARG ENDP
  389.  
  390.         PAGE +
  391. ;********************************************************************
  392. ; THIS IS THE MOVE SUBROUTINE. IT ASSUMES THAT ARG1 AND ARG2 ARE
  393. ; SET UP PROPERLY IN THE RECURSION STACK AREA, AND THAT "RBASE" POINTS
  394. ; TO THE START OF THE DATA STRUCTURE FOR THIS RECURSION LEVEL.
  395. ;
  396. MOVEIT  PROC    NEAR
  397.         MOV     BX,WORD PTR DS:RBASE    ;GET BASE ADDR. (POINTER TO MVINFO)
  398.         CALL    SETUP                   ;PARSE ARGUMENTS, CHECK FOR ERRORS
  399.         JNC     NOARGERR                ;IF OK
  400.         JMP     EXIT2                   ;QUIT IF ERROR
  401. ;******************************************
  402. ; SEE IF ANYTHING MATCHES THE SOURCE SPEC *
  403. ;******************************************
  404. NOARGERR:
  405.         ADDR    DX,SSPATH               ;POINT TO SEARCH PATH
  406.         MOV     CX,31H                  ;SET SEARCH ATTRIBUTES
  407.         MOV     AH,FIND_FIRST
  408.         INT     DOS                     ;SEARCH FOR 1ST MATCH
  409.         JNC     SRCOK                   ;OK IF SOMETHING FOUND
  410.         ADDR    DX,ARG1
  411.         CALL    ERRORMSG                ;ELSE SHOW ARGUMENT
  412.         ERROR   2                       ;SAY IT DOESN'T EXIST
  413.     MOV    AL,2            ;SET ERROR CODE
  414.         JMP     EXIT2
  415. ;**************************************
  416. ; CREATE DEST DIRECTORY, IF NECESSARY *
  417. ;**************************************
  418. SRCOK:  CMP     WORD PTR [BX].NEWDIR,1  ;CHECK NEW DIRECTORY FLAG
  419.         JNE     GOTONE                  ;IF NOT SET
  420.         ADDR    DX,ARG2A                ;POINT TO DEST NAME
  421.         MOV     AH,MKDIR
  422.         INT     DOS                     ;CREATE NEW DIRECTORY
  423.         JNB     GOTONE                  ;IF OK
  424.         ADDR    DX,ARG2A                ;IF CAN'T CREATE,
  425.         CALL    ERRORMSG                ;SHOW DIRECTORY NAME
  426.         ERROR   12                      ;AND ERROR MSG.
  427.     MOV    AL,12            ;SET ERROR CODE
  428.         JMP     EXIT2                   ;EXIT 2 DOS
  429. ;**************
  430. ; TOP OF LOOP *
  431. ;**************
  432. GOTONE:
  433.         CALL    BUILD_NAMES             ;MAKE UNAMBIG. SOURCE AND DEST NAMES
  434.         JNC     NOSKIP
  435.         JMP     NEXTFILE                ;IF SOURCE IS "." OR ".." OR = DEST
  436. NOSKIP:
  437.         CMP     BYTE PTR DS:VFLAG,TRUE  ;CHECK VERBOSE FLAG
  438.         JNE     QUIET                   ;IF QUIET MODE
  439.         ADDR    DX,SRCNAME              ;NOT QUIET, SHOW VERBIAGE
  440.         CALL    ERRORMSG
  441.         CALL    TYPTX
  442.         DB      ' -->',SPACE+200Q
  443.         ADDR    DX,DESTNAME
  444.         CALL    ERRORMSG
  445.         CALL    CRLF
  446. QUIET:
  447.         TEST    [BX].DTA+21,BIT$DIR     ;IS SOURCE A DIRECTORY?
  448.         JZ      CHKDRIVES               ;NO
  449. ;***********************************************
  450. ; IF SOURCE IS A DIRECTORY, RECURSIVELY MOVE IT*
  451. ;***********************************************
  452.     CMP    BYTE PTR DS:RFLAG,TRUE    ;R FLAG SET?
  453.     JNE    NEXTFILE        ;NO, SKIP OVER DIRECTORY
  454.         CMP     WORD PTR DS:LEVEL,MAXLEVEL-1 ;ARE WE AT MAX LEVEL?
  455.         JL      NOTMAX                  ;NO
  456.         ERROR   14                      ;YES, TOO DEEP
  457.     MOV    AL,14            ;SET ERROR CODE
  458.         JMP     EXIT2
  459. NOTMAX:
  460.         COPYPATH SRCNAME,(ARG1+MVSTRUCSIZE)  ;COPY SOURCE DIRECTORY TO ARG1 AT NEXT LEVEL
  461.         COPYPATH DESTNAME,(ARG2+MVSTRUCSIZE) ;COPY DEST NAME TO ARG2 AT NEXT LEVEL
  462.         PUSH    BX                      ;SAVE POINTER TO BASE
  463.         INC     WORD PTR DS:LEVEL       ;INCREMENT RECURSION LEVEL
  464.         ADD     WORD PTR DS:RBASE,MVSTRUCSIZE ;ADVANCE BASE POINTER
  465.         CALL    MOVEIT                  ;MOVE THE DIRECTORY
  466.         POP     BX                      ;RESTORE BASE POINTER
  467.         DEC     WORD PTR DS:LEVEL       ;DECREMENT RECURSION LEVEL
  468.         SUB     WORD PTR DS:RBASE,MVSTRUCSIZE  ;RESTORE BASE TO PREVIOUS LEVEL
  469.         ADDR    DX,DTA
  470.         MOV     AH,SET_DTA
  471.         INT     DOS                     ;RESET DTA
  472.         JMP     SHORT NEXTFILE          ;DO NEXT FILE
  473. ;*****************************************
  474. ; IF SOURCE IS A FILE, COPY OR RENAME IT *
  475. ;*****************************************
  476. CHKDRIVES:
  477.         MOV     AL,BYTE PTR DS:SRCDRIVE    ;GET SOURCE DRIVE
  478.         CMP     AL,BYTE PTR DS:DESTDRIVE   ;COMPARE W. DEST..
  479.         JNE     MOVEM
  480.         CALL    RENAME_FILE             ;SAME DRIVE, JUST RENAME
  481.     JNB    NEXTFILE
  482.     JMP    EXIT2            ;ERROR, EXIT TO DOS
  483. MOVEM:  CALL    COPY_FILE               ;DIFFERENT DRIVE, COPY SOURCE TO DEST
  484.     JNB    NEXTFILE
  485.     JMP    EXIT2            ;ERROR, EXIT TO DOS
  486. ;*****************
  487. ; BOTTOM OF LOOP *
  488. ;*****************
  489. NEXTFILE:
  490.         MOV     AH,FIND_NEXT
  491.         INT     DOS                     ;FIND NEXT MATCH, IF ANY
  492.         JC      NOMORE                  ;IF NONE
  493.         JMP     GOTONE                  ;GOT ONE, BACK TO TOP OF LOOP
  494. ;**********************
  495. ; NO MORE FILES, DONE *
  496. ; *********************
  497. NOMORE: MOV     AX,WORD PTR [BX].SRCTYPE    ;GET TYPE OF SOURCE
  498.         CMP     AX,TYPE_DIR             ;DIRECTORY?
  499.         JNE     JUSTCLOSE               ;NO
  500.         ADDR    DX,ARG1                 ;YES, POINT TO NAME
  501.         MOV     AH,RMDIR
  502.         INT     DOS                     ;REMOVE IT
  503.         JNB     JUSTCLOSE
  504.         ADDR    DX,ARG1
  505.         CALL    ERRORMSG
  506.         ERROR   13                      ;COMPLAIN IF ERROR
  507.         CALL    CLOSE2            ;CLOSE OUTPUT FILE
  508.     MOV    AL,13            ;SET ERROR CODE
  509.     JMP    EXIT2            ;EXIT TO DOS
  510.     
  511. ;**************
  512. ; NORMAL EXIT *
  513. ;**************
  514. JUSTCLOSE:
  515.     CALL    CLOSE2            ;CLOSE OUTPUT FILE
  516.     CALL    CLOSE1            ;CLOSE INPUT FILE
  517.         RET                             ;ALL DONE
  518. MOVEIT  ENDP
  519.  
  520.         PAGE +
  521. ;*************************************************************************
  522. ; THIS PROCEDURE PARSES ARG1 AND ARG2 AND CHECKS FOR INCOMPATIBLE TYPES
  523. ; (E.G. "MV FOOBAR *.*").  IF SUCCESSFUL, IT SETS SSPATH = SOURCE SEARCH
  524. ; PATH, SPREFIX = SOURCE PREFIX, DSPATH = DEST SEARCH PATH (NOT USED),
  525. ; DPREFIX = DEST PREFIX, SRCTYPE = SOURCE TYPE DESTTYPE = DESTINATION TYPE.
  526. ; IT ALSO SETS "NEWDIR"=1 IF THE DESTINATION DIRECTORY MUST BE CREATED.
  527. ; ALL OF THESE VARIABLES ARE IN A STRUCTURE OF TYPE 'MVINFO' IN THE RECURSION
  528. ; STACK AREA (STARTING AT THE ADDRESS IN 'RBASE').
  529. ;
  530. ; ON RETURN, THE CARRY FLAG IS SET IF AN ERROR OCCURRED, AND AL HOLDS AN
  531. ; ERROR CODE KEYED TO THE ERROR MESSAGE NUMBER.
  532. ;
  533. SETUP   PROC    NEAR
  534.         MOV     BX,WORD PTR DS:RBASE    ;GET ADDR. OF DATA STRUCTURE
  535.         MOV     WORD PTR [BX].NEWDIR,0  ;CLEAR "NEW DIRECTORY" FLAG
  536.         ADDR    DX,DTA
  537.         MOV     AH,SET_DTA
  538.         INT     DOS                     ;SET DTA
  539.         ADDR    SI,ARG1
  540.         ADDR    DI,ARG2
  541.         COMP_STRINGS                    ;COMPARE ARG1 AND ARG2
  542.         JNE     NOTIDENT                ;IF NOT IDENTICAL
  543.         ERROR   17                      ;ARG1 = ARG2, BAD NEWS
  544.     MOV    AL,17
  545.         STC
  546.         RET
  547. NOTIDENT:
  548.         ADDR    CX,SSPATH
  549.         ADDR    DX,SPREFIX
  550.         PUSH    BX
  551.         ADD     BX,ARG1
  552.         CALL    FIXPATH                 ;PARSE SOURCE PATHNAME
  553.         POP     BX
  554.         CMP     AX,TYPE_UNK
  555.         JNE     GOODPATH                ;IF APPARENTLY OK
  556.         ADDR    DX,ARG1
  557.         CALL    ERRORMSG
  558.         ERROR   2                       ;NONEXISTENT PATHNAME, COMPLAIN
  559.     MOV    AL,2
  560.         STC
  561.         RET
  562. GOODPATH:
  563.         MOV     WORD PTR [BX].SRCTYPE,AX     ;SAVE TYPE OF SOURCE
  564.     CMP    AX,TYPE_DIR             ;IS IT A DIRECTORY?
  565.     JNE    RSET                 ;NO.
  566.     CMP    BYTE PTR DS:RFLAG,TRUE         ;R FLAG SET?
  567.     JE    RSET            ;IF OK
  568.     ADDR    DX,ARG1            ;SHOW NAME
  569.     CALL    ERRORMSG
  570.     ERROR    7            ;COMPLAIN ABOUT DIRECTORY
  571.     MOV    AL,7
  572.     STC                ;SIGNAL ERROR
  573.     RET
  574. RSET:
  575.         ADDR    SI,ARG2            ;GET POINTER TO DEST
  576. PDEST:  PUSH    SI            ;SAVE IT ON STACK
  577.     MOV    DI, SI            ;AND IN DI
  578. SRCBS:  MOV     AX,[SI]                 ;FIND END OF DEST
  579.         COMPLIST <0,SPACE,TAB>,GOTEND
  580.         INC     SI
  581.         JMP     SRCBS
  582. GOTEND:
  583.         DEC     SI
  584.         CMP     [SI],BYTE PTR '\'       ;DOES DEST SPEC END W. BACKSLASH?
  585.         JNE     NOBS                    ;J/NO, IT DOESN'T
  586.     CMP    SI, DI            ;IS DEST="\"?
  587.     JE    NOBS            ;J/YES, ROOT DIRECTORY, LEAVE IT ALONE
  588.     CMP    BYTE PTR [SI-1],':'    ;IS PREVIOUS CHAR ':'?
  589.     JE    NOBS            ;J/YES, ROOT DIRECTORY, LEAVE IT ALONE
  590.         MOV     [SI],BYTE PTR 0         ;\ AT END AND NOT ROOT DIR, REMOVE IT
  591. NOBS:   COPYPATH ARG2,ARG2A             ;MAKE ARG2A = ARG2
  592.         ADDR    CX, DSPATH
  593.         ADDR    DX, DPREFIX
  594.     POP    SI            ;GET POINTER TO ARG2 AGAIN
  595.         PUSH    BX
  596.         MOV     BX, SI
  597.         CALL    FIXPATH                 ;PARSE DEST PATHNAME
  598.         POP     BX
  599.         MOV     WORD PTR [BX].DESTTYPE,AX       ;SAVE DEST TYPE
  600.         CMP     AL,TYPE_AFN
  601.         JE      BADDEST                 ;DEST CAN'T BE AFN
  602.         CMP     AL,TYPE_UFN
  603.         JNE     NOTUFN                  ;IF DEST TYPE IS UFN,
  604.         CMP     WORD PTR DS:NUMARGS,2   ;BETTER HAVE ONLY 1 SOURCE
  605.         JG      BADDEST
  606.         CMP     WORD PTR DS:SRCTYPE,TYPE_AFN  ;AND SOURCE TYPE BETTER NOT BE AFN
  607.         JNE     NOTUFN
  608. BADDEST:
  609.         ERROR   3
  610.     MOV    AL,3
  611.         STC
  612.         RET
  613. NOTUFN:
  614.         COMPLIST <TYPE_DSP,TYPE_DRV,TYPE_DIR>,DESTDSP ;IF DEST IS DIR OR DRIVE
  615.         CMP     AL,TYPE_UNK
  616.         JNE     SHORT DESTOK            ;IF DEST EXISTS
  617.  
  618. DESTNX:
  619.         MOV     AX,WORD PTR [BX].SRCTYPE  ;DEST DOESN'T EXIST
  620.         CMP     AL,TYPE_DIR             ;IF SOURCE IS DIRECTORY,
  621.         JE      DESTDIR            ;MAKE DEST A DIRECTORY, TOO
  622.     CMP    AL,TYPE_AFN         ;SOURCE NOT A DIRECTORY
  623.     JE    BADDEST            ;AFN IS BAD (E.G. MV *.* FOO)
  624.     JMP    SHORT DESTOK        ;OTHERWISE OK
  625. DESTDIR:
  626.         CALL    SETUP_DEST_DIR          ;MAKE DEST A DIRECTORY, TOO
  627.         JMP     SHORT DESTOK
  628. DESTDSP: MOV    AX,WORD PTR [BX].SRCTYPE  ;DEST IS DIRECTORY, DIR SPEC OR DRIVE
  629.         CMP     AL,TYPE_DIR             ;IS SOURCE A DIRECTORY? -
  630.         JNE     DESTOK                  ;- NO
  631.         CALL    SETUP_SRC_DIR           ;- YES, SOURCE IS DIRECTORY, SET IT UP
  632.         JB      ERRRET                  ;IF ERROR
  633.         MOV     AX,WORD PTR [BX].DESTTYPE
  634.         CMP     AX,TYPE_DIR             ;IS DEST A DIRECTORY? -
  635.         JNE     DESTOK                  ;- NO
  636.         CALL    SETUP_DEST_DIR          ;- YES, SET IT UP, TOO
  637. ;*******************************
  638. ; CHECK FOR INCOMPATIBLE TYPES *
  639. ;*******************************
  640. DESTOK:
  641.         MOV     CX,WORD PTR [BX].DESTTYPE    ;GET DEST TYPE
  642.         MOV     AX,WORD PTR [BX].SRCTYPE     ;GET SOURCE TYPE
  643.         CMP     AX,TYPE_DIR             ;IS SOURCE A DIRECTORY? -
  644.         JNE     TYPEOK                  ;- NO, IT ISN'T
  645.         CMP     CX,TYPE_DIR             ;- YES, SOURCE IS DIRECTORY,
  646.         JE      TYPEOK                  ;DEST BETTER BE DIRECTORY
  647.         CMP     CX,TYPE_DRV             ;OR DRIVE SPEC
  648.         JE      TYPEOK
  649. ERRRET:
  650.         ERROR   3                       ;ELSE INCOMPATIBLE TYPE ERROR
  651.     MOV    AL,3
  652.     STC                             ;ERROR RETURN
  653.         RET
  654. TYPEOK: CLC                             ;NORMAL RETURN
  655.         RET
  656. SETUP   ENDP
  657.  
  658. ;**********************************************
  659. ; MOVE IS FROM DIR TO DIR, DIR SPEC OR DRIVE
  660. ; BUILD FULL DEST PATHNAME (IN ARG2A) AND CHECK
  661. ; ITS TYPE.  (SETS CARRY ON ERROR)
  662. ;
  663. SETUP_SRC_DIR PROC NEAR
  664.         COPYPATH ARG2,DSPATH            ;COPY DEST DIRECTORY OR DRIVE SPEC TO
  665.                                         ;DEST PATH (USE AS SCRATCH AREA)
  666.         DEC     DI                      ;BACK UP OVER NULL
  667.         MOV     AX,WORD PTR [BX].DESTTYPE
  668.         CMP     AX,TYPE_DIR             ;SEE IF DEST IS DIRECTORY
  669.         JNE     NOTDIR                  ;NOPE
  670.         MOV     BYTE PTR [DI],'\'       ;YES, ADD BACKSLASH TO DEST NAME
  671.         INC     DI
  672.         DEC     CX
  673. NOTDIR: ADDR    SI,ARG1                 ;POINT TO SOURCE DIRECTORY NAME
  674.         CMP     BYTE PTR [SI+1],':'     ;DRIVE SPECIFIED? -
  675.         JNE     NODRV                   ;- NO IT WASN'T
  676.         ADD     SI,2                    ;- YES, IT WAS, SKIP IT
  677. NODRV:
  678. ;    skip to the last element in the source path
  679.     MOV    DX, SI            ;SAVE START OF SOURCE IN DX
  680. STRIP_PATH:
  681.     CMP    BYTE PTR [SI],0        ;END OF SOURCE?
  682.     JE    END_OF_SRC        ;J/YES
  683.     CMP    BYTE PTR [SI],'\'    ;BACKSLASH IN SOURCE?
  684.     JNE    NEXT_CHAR        ;J/NO, KEEP SEARCHING
  685.     MOV    DX, SI            ;SAVE LOCATION OF BACKSLASH
  686. NEXT_CHAR:
  687.     INC    SI
  688.     JMP    STRIP_PATH
  689. END_OF_SRC:
  690.     MOV    SI, DX            ;POINT TO LAST \ OR START OF STRING
  691.     CMP    BYTE PTR [SI],'\'    ;IS NEXT CHAR. \?
  692.     JNE    NOBKSL            ;NO
  693.     INC    SI            ;YES, SKIP PAST IT
  694. NOBKSL:
  695.         CALL    CPYCNT                  ;COPY LAST PART OF SOURCE DIRECTORY
  696.                     ;NAME TO DEST PATH
  697.         COPYPATH DSPATH,ARG2A           ;COPY AUGMENTED DEST PATH TO ARG2A
  698.         ADDR    CX,DSPATH
  699.         ADDR    DX,DPREFIX
  700.         PUSH    BX
  701.         ADD     BX,ARG2A
  702.         CALL    FIXPATH                 ;PARSE FULL DEST PATHNAME
  703.         POP     BX
  704.         MOV     WORD PTR [BX].DESTTYPE,AX    ;SAVE DEST TYPE
  705.         CMP     AL,TYPE_UNK
  706.         JNE     DESTXST                 ;IF DEST EXISTS
  707.         MOV     AX,WORD PTR [BX].SRCTYPE  ;DEST DOESN'T EXIST, GET SOURCE TYPE
  708.         CMP     AX,TYPE_DIR             ;IF SOURCE IS A DIRECTORY,
  709.         JNE     DESTXST
  710.         MOV     [BX].DESTTYPE,TYPE_DIR  ;MAKE DEST A DIRECTORY, TOO
  711. DESTXST:
  712.         CLC
  713.         RET
  714. SETUP_SRC_DIR ENDP
  715.  
  716. ;***************************************************************
  717. ; THIS PROCEDURE IS CALLED IF THE DESTINATION IS A NEW DIRECTORY
  718. ;
  719. SETUP_DEST_DIR PROC NEAR
  720.         ADDR    SI,DSPATH
  721.         ADDR    DI,DPREFIX
  722.         PUSH    DI
  723.         MOV     CX,PATHSIZE
  724.         CALL    CPYCNT                  ;COPY SEARCH PATH TO PREFIX
  725.         POP     DI
  726.         MOV     CX,PATHSIZE
  727.         MOV     AL,0
  728.         REPNE   SCASB                   ;FIND END OF DEST PREFIX
  729.         DEC     DI
  730.         MOV     [DI],BYTE PTR '\'       ;ADD BACKSLASH
  731.         MOV     [DI+1],BYTE PTR 0
  732.         MOV     [BX].NEWDIR,WORD PTR 1  ;SET "NEW DIRECTORY FLAG"
  733.         MOV     WORD PTR [BX].DESTTYPE,TYPE_DIR ;SET DEST TYPE = DIRECTORY
  734.         RET
  735. SETUP_DEST_DIR ENDP
  736.  
  737.         PAGE +
  738. ;****************************************************************************
  739. ; THIS ROUTINE TAKES THE INFO ON A FILE IN THE DTA AND USES IT TO GENERATE
  740. ; FULL, UNAMBIGUOUS SOURCE AND DESTINATION FILE NAMES BY ADDING THE NECESSARY
  741. ; DIRECTORY PREFIXES TO IT.  IT SETS THE CARRY FLAG IF THE "FILE"
  742. ; IS "." OR "..", OR IF THE SOURCE IS IDENTICAL TO THE DESTINATION.
  743. ;
  744. BUILD_NAMES  PROC  NEAR
  745.         COPYPATH SPREFIX,SRCNAME        ;GET SOURCE PREFIX, COPY TO SOURCE NAME
  746.         DEC     DI                      ;BACK UP OVER NULL
  747.         ADDR    SI,(DTA+30)             ;POINT TO FILE NAME WE FOUND
  748.         CMP     [SI],BYTE PTR '.'       ;DOES IT START WITH .? -
  749.         JNE     NOTDOT                  ;- NO
  750.         STC                             ;- YES, SET CARRY TO SKIP IT
  751.         RET
  752. NOTDOT:
  753.         CALL    CPYCNT                  ;ADD IT TO SOURCE PREFIX
  754.         CMP     WORD PTR [BX].DESTTYPE,TYPE_UFN  ;IS DEST A UFN?
  755.         JE      DESTUFN                 ;YES, JUST USE IT
  756.         CMP     WORD PTR [BX].DESTTYPE,TYPE_UNK
  757.         JE      DESTUFN                 ;DITTO IF DEST DOESN'T EXIST
  758.                                         ;IF NOT, MAKE DEST NAME = SOURCE NAME
  759.         COPYPATH DPREFIX,DESTNAME       ;COPY DEST PREFIX TO DEST NAME
  760.         DEC     DI                      ;BACK UP OVER NULL
  761.         ADDR    SI,DTA+30               ;POINT TO FILE NAME WE FOUND
  762.         CALL    CPYCNT                  ;ADD IT TO DEST PREFIX
  763.         JMP     SHORT DONE              ;GO TO NEXT STEP
  764. DESTUFN:                                ;DEST IS A FILE, NOT A DIRECTORY
  765.         COPYPATH ARG2,DESTNAME          ;SO DESTNAME JUST = ARG2
  766. DONE:
  767.         CALL    CHECK_NAMES             ;CHECK SOURCE AND DEST FOR IDENTITY
  768.         RET
  769. BUILD_NAMES ENDP
  770.  
  771.         PAGE +
  772. ;*********************************************************************
  773. ; THIS PROCEDURE CHECKS THE SOURCE AND DEST FILES, AND SETS THE CARRY
  774. ; FLAG IF THEY ARE IDENTICAL
  775. ;
  776. CHECK_NAMES PROC NEAR
  777.         MOV     BX,WORD PTR RBASE        ;GET ADDR. OF DATA STRUCTURE
  778.         MOV     AH,SET_DTA
  779.         MOV     DX,OFFSET DEST_DTA
  780.         INT     DOS                     ;SET DTA
  781.         ADDR    DX,DESTNAME             ;POINT TO DESTINATION
  782.         MOV     CX,0FFH
  783.         MOV     AH,FIND_FIRST
  784.         INT     DOS                     ;SEARCH FOR IT
  785.         PUSHF
  786.         ADDR    DX,DTA
  787.         MOV     AH,SET_DTA
  788.         INT     DOS                     ;RESET DTA
  789.         POPF
  790.         JNB     GOTDEST                 ;IF FOUND IT
  791.         CLC                             ;OK IF IT DOESN'T EXIST
  792.         RET
  793. GOTDEST: ADDR   SI,DTA+21               ;POINT TO INFO ON SOURCE
  794.         MOV     DI,OFFSET DEST_DTA+21   ;POINT TO INFO ON DEST
  795.         MOV     CX,9                    ;SIZE OF FILE ATTRIBUTES
  796.         REPE    CMPSB                   ;COMPARE SOURCE AND DEST
  797.         JNE     NOTEQU                  ;IF NOT =
  798.         COMP_STRINGS                    ;COMPARE STRINGS
  799.         JNE     NOTEQU                  ;IF SOURCE AND DEST NAMES NOT EQUAL
  800.         STC                             ;FILES ARE EQUAL (NAMES AND ATTRIB.)
  801.         RET
  802. NOTEQU: CLC
  803.         RET
  804. CHECK_NAMES ENDP
  805.         PAGE +
  806. ;**************************************************************************
  807. ; THIS ROUTINE COPIES A SINGLE FILE (SRCNAME) TO ITS DESTINATION (DESTNAME)
  808. ; ON ANOTHER DISK.
  809. ;
  810. ; IT SETS THE CARRY FLAG IF AN ERROR OCCURRED.
  811. ;
  812. COPY_FILE PROC  NEAR
  813.         ADDR    DX,SRCNAME              ;DX = SOURCE FILE NAME
  814.         MOV     AL,READ_ACCESS
  815.         MOV     AH,DOS2_OPEN
  816.         INT     DOS                     ;TRY TO OPEN SOURCE FILE
  817.         JC      FAIL                    ;IF CAN'T
  818.         MOV     WORD PTR INHANDLE,AX    ;SAVE FILE HANDLE
  819.         CALL    GETOK                   ;GET CONFIRMATION IF DEST EXISTS
  820.         JNC     OKGIVEN                 ;IF OK TO DELETE
  821.         MOV     BX,WORD PTR INHANDLE     ;IF NOT OK, GET FILE HANDLE
  822.         MOV     AH,DOS2_CLOSE
  823.         INT     DOS                     ;CLOSE INPUT FILE
  824.     CLC
  825.         RET                             ;EXIT W/O MOVING
  826. FAIL:   ADDR    DX,SRCNAME              ;POINT TO SOURCE FILE NAME
  827.         CALL    ERRORMSG                ;SHOW IT
  828.         ERROR   5                       ;COMPLAIN THAT CAN'T OPEN
  829.     MOV    AL,5
  830.     STC
  831.     RET
  832. OKGIVEN: ADDR   DX,DESTNAME
  833.         MOV     CL,BYTE PTR [BX].DTA+21  ;MAKE DEST ATTRIBUTES=SOURCE ATTRIB.
  834.         MOV     CH,0
  835.         MOV     AH,DOS2_CREATE
  836.         INT     DOS                     ;CREATE FILE (OR TRUNCATE OLD ONE)
  837.         JNC     CREATED                 ;IF OK
  838.         ADDR    DX,DESTNAME
  839.         CALL    ERRORMSG                ;CREATE FAILED, SHOW FILE NAME
  840.         ERROR   5                       ;COMPLAIN THAT CAN'T OPEN
  841.     MOV    AL,5
  842.     STC
  843.     RET
  844. CREATED:
  845.         MOV     WORD PTR OUTHANDLE,AX   ;SAVE OUTPUT HANDLE
  846. COPYLOOP:
  847.         PUSH    BX
  848.         MOV     BX,WORD PTR INHANDLE     ;BX = FILE HANDLE
  849.         MOV     DX,OFFSET BUFFER        ;DX = BUFFER OFFSET
  850.         MOV     CX,BUFSIZE              ;CX = BUFFER SIZE
  851.         MOV     AH,READ                 ;USING DOS 2 CALL,
  852.         INT     DOS                     ;READ FROM SOURCE
  853.         POP     BX
  854.         JC      RDERR                   ;IF ERROR
  855.         MOV     CX,AX                   ;SAVE AMT. READ
  856.         CMP     AX,0
  857.         JE      ENDCOPY                 ;IF 0
  858.         PUSH    BX
  859.         MOV     BX,WORD PTR OUTHANDLE     ;BX = FILE HANDLE
  860.         MOV     DX,OFFSET BUFFER        ;DX = BUFFER OFFSET
  861.         MOV     AH,WRITE
  862.         INT     DOS                     ;WRITE BUFFER TO DEST
  863.         POP     BX
  864.         JC      WRERR                   ;IF ERROR
  865.         CMP     AX,CX                   ;WERE ALL BYTES WRITTEN?
  866.         JE      COPYLOOP                ;YES, KEEP GOING
  867.     ADDR    DX,DESTNAME        ;POINT TO DEST NAME
  868.     CALL    ERRORMSG        ;SHOW IT
  869.         ERROR   10                      ;PROBABLY DISK FULL
  870.     MOV    AL,10            ;SET ERROR CODE
  871.     JMP     SCRATCH            ;ABORT
  872. WRERR:  ADDR    DX,DESTNAME        ;POINT TO DEST NAME
  873.     CALL    ERRORMSG        ;SHOW IT
  874.     ERROR   8                       ;WRITE ERROR
  875.     MOV    AL,8            ;SET ERROR CODE
  876.         JMP     SCRATCH                 ;ABORT
  877. RDERR:  ADDR    DX,SRCNAME        ;POINT TO SOURCE NAME
  878.     CALL    ERRORMSG        ;SHOW IT
  879.     ERROR   9                       ;READ ERROR
  880.     MOV    AL,9            ;SET ERROR CODE
  881.         JMP     SCRATCH                 ;ABORT
  882. ENDCOPY: PUSH   BX                      ;NO ERRORS
  883.         MOV     BX,WORD PTR INHANDLE    ;GET INPUT FILE HANDLE
  884.         MOV     AH,FILE_TIMES
  885.         MOV     AL,0                    ;GET DATE AND TIME
  886.         INT     DOS                     ;GET IT
  887.         MOV     BX,WORD PTR OUTHANDLE   ;GET OUTPUT FILE HANDLE
  888.         MOV     AH,FILE_TIMES
  889.         MOV     AL,1
  890.         INT     DOS                     ;SET OUTPUT DATE AND TIME SAME AS INPUT
  891.         MOV     BX,WORD PTR INHANDLE
  892.         MOV     AH,DOS2_CLOSE
  893.         INT     DOS                     ;CLOSE INPUT FILE
  894.         MOV     BX,WORD PTR OUTHANDLE
  895.         MOV     AH,DOS2_CLOSE
  896.         INT     DOS                     ;CLOSE OUTPUT FILE
  897.         POP     BX
  898.         ADDR    DX,SRCNAME              ;POINT TO SOURCE NAME
  899.     CALL    UNLINK2            ;REMOVE IT
  900.         JB      DELERR                  ;IF SOME PROBLEM
  901.         RET                             ;ALL DONE
  902. DELERR: ADDR    DX,SRCNAME              ;CAN'T DELETE FILE, SHOW FILE NAME
  903.         CALL    ERRORMSG
  904.         ERROR   13                      ;AND ERROR MSG.
  905.     MOV    AL,13
  906.     STC
  907.         RET
  908.  
  909. SCRATCH:
  910.     PUSH    AX            ;SAVE ERROR CODE
  911.     PUSH    BX
  912.     MOV    BX,WORD PTR OUTHANDLE
  913.     MOV    AH,DOS2_CLOSE
  914.     INT    DOS            ;CLOSE OUTPUT FILE
  915.     POP    BX
  916.     ADDR    DX,DESTNAME
  917.     CALL    UNLINK2            ;REMOVE PARTIAL FILE
  918.     POP    AX
  919.     STC
  920.     RET
  921.  
  922. COPY_FILE ENDP
  923.  
  924. PAGE +
  925. ;*******************************************************************
  926. ; THIS ROUTINE "MOVES" A FILE (SRCNAME) BY RENAMING IT (TO DESTNAME)
  927. ;
  928. ; IT SETS THE CARRY FLAG IF AN ERROR OCCURRED.
  929. ;
  930. RENAME_FILE PROC NEAR
  931.         CALL    GETOK                   ;SEE IF FILE EXISTS
  932.         JNC     OK                      ;USER SAID OK TO ERASE
  933.     MOV    AL,4
  934.     STC
  935.         RET                             ;NOT OK, SKIP THIS ONE
  936. OK:     ADDR    DX,SRCNAME              ;POINT TO SOURCE
  937.         ADDR    DI,DESTNAME             ;AND DEST
  938.         MOV     AH,DOS2_RENAME
  939.         PUSH    BX
  940.         INT     DOS                     ;RENAME
  941.         POP     BX
  942.         JNC     RENOK                   ;IF OK
  943.         ADDR    DX,SRCNAME
  944.         CALL    ERRORMSG                ;SHOW SOURCE
  945.         ERROR   11                      ;SHOULDN'T HAPPEN
  946.     MOV    AL,11            ;SET ERROR CODE
  947.     STC                ;SIGNAL ERROR
  948. RENOK:  RET
  949. RENAME_FILE ENDP
  950.  
  951.         PAGE +
  952. ;*******************************************************************
  953. ;       THIS ROUTINE CHECKS TO SEE IF THE DEST FILE EXISTS.
  954. ;       IF IT DOES, AND IF THE CONFIRM FLAG IS SET, IT ASKS
  955. ;       FOR CONFIRMATION BEFORE DELETING THE FILE.  IF THE
  956. ;       CONFIRM FLAG IS NOT SET, IT JUST DELETES IT.
  957. ;       ON EXIT, 'C'=1 IF THE USER REPLIED 'N' TO THE CONFIRM MSG.
  958. ;
  959. GETOK   PROC    NEAR
  960.         ADDR    DX,DESTNAME
  961.         MOV     AL,0
  962.         MOV     AH,CHMOD
  963.         INT     DOS                     ;GET ATTRIBUTES FOR DEST
  964.         JNC     EXISTS                  ;IF FILE EXISTS
  965.         CLC
  966.         RET
  967. EXISTS:
  968.         CMP     BYTE PTR DS:IFLAG,TRUE  ;IS FLAG SET TO CONFIRM?
  969.         JNE     COK                     ;NO.
  970.         ADDR    DX,DESTNAME
  971.         CALL    ERRORMSG                ;SHOW DEST FILE
  972.         ERROR   4                       ;ASK FOR CONFIRMATION
  973.     CALL    GETYORN            ;GET Y OR N RESPONSE
  974.         CMP     AL,'Y'                  ;IS IT YES?
  975.         JNE     ABEXIT                  ;NO, SIGNAL CALLING ROUTINE
  976. COK:
  977. TRYAGAIN:
  978.         ADDR    DX,DESTNAME
  979.         MOV     AH,UNLINK
  980.         INT     DOS                     ;DELETE THE FILE
  981.         JNC     OKEXIT                  ;IF NO PROBLEM
  982.         CMP     AX,5                    ;WAS FILE R/O? (THIS OUGHT TO BE
  983.                                         ; THE ONLY POSSIBLE ERROR)
  984.         JNE     OKEXIT                  ;EXIT IF SOME OTHER ERROR
  985.     ADDR    DX,DESTNAME
  986.     CALL    ERRORMSG        ;SHOW DEST FILE NAME
  987.         ERROR   6                       ;R/O FILE, QUERY USER AGAIN
  988.     CALL    GETYORN            ;GET Y OR N RESPONSE
  989.         CMP     AL,'Y'                  ;TEST FOR 'Y' RESPONSE
  990.         JNE     ABEXIT                  ;ABORT IF USER SAYS 'N'
  991.         MOV     CX,0                    ;'Y' TYPED CLEAR ALL ATTRIBUTES
  992.         ADDR    DX,DESTNAME             ;POINT TO FILE NAME
  993.         MOV     AH,CHMOD
  994.         MOV     AL,1                    ;CHANGE ATTRIBUTES
  995.         INT     DOS                     ;TRY MAKING IT R/W
  996.         JMP     TRYAGAIN                ;TRY TO ERASE IT AGAIN
  997. ABEXIT: STC
  998.         RET
  999. OKEXIT: CLC
  1000.         RET
  1001. GETOK   ENDP
  1002.  
  1003. ; PRTERR = PRINT ERROR MESSAGE (DX POINTS TO OFFSET FROM DGROUP)
  1004.  
  1005. PRTERR: PUSH    DS
  1006.         MOV     AX,DGROUP
  1007.         MOV     DS,AX
  1008.         CALL    ERRORMSG
  1009.         POP     DS
  1010.     RET
  1011.  
  1012. CLOSE2:  MOV    BX,WORD PTR OUTHANDLE
  1013.         MOV     AH,DOS2_CLOSE
  1014.         INT     DOS                     ;CLOSE OUTPUT FILE
  1015.     RET
  1016. CLOSE1:
  1017.         MOV     BX,WORD PTR INHANDLE
  1018.         MOV     AH,DOS2_CLOSE
  1019.         INT     DOS                     ;CLOSE INPUT FILE
  1020.     RET
  1021. EXIT2:
  1022.         MOV     AH,EXIT
  1023.         INT     DOS                     ;EXIT TO DOS
  1024.  
  1025.         END     ENTRY
  1026.  
  1027.  
  1028.